thirdfridayOf

I would like to find the third friday of every month is there a better way of doing it? Thank you.

 

-Jim

Date nextDay(Date cDate, int x)
{
    return(dateOnly(dateOf((intOf cDate) + 60*60*24*x)))
} // nextDay

Date xDayMonthOf(Date cDate, string day, int count) {
    const string Month = (stringOf(cDate, userLocale(), "MMMM"))
    const string Year = (stringOf(cDate, userLocale(), "yyyy"))
    int cnt = 1

    while((stringOf(cDate, userLocale(), "dddd")) != day) {
        cDate = (string (++cnt " " Month " " Year))
    }
    
    cDate = nextDay(cDate, ((--count)*7))
    if(Month != (stringOf(cDate, userLocale(), "MMMM"))) {
        cDate = "01 January 1970"
        return dateOnly(cDate)
    } else {
        return dateOnly(cDate)
    }
} // xDayMonthOf

Date xDayMonthOf(string day, int count) {
    return xDayMonthOf(today(), day, count)
} // xDayMonthOf

print xDayMonthOf(today(), "Friday", 3) "\n"
print xDayMonthOf("Friday", 3) "\n"
print xDayMonthOf("Monday", 5) "\n"

print xDayMonthOf(today(), "Friday", 1) "\n"
print xDayMonthOf("Friday", 1) "\n"

Date cDate = "20 December 2014"
print xDayMonthOf(cDate, "Friday", 3) "\n"

/*
output:
20 December 2013
20 December 2013
30 December 2013
06 December 2013
06 December 2013
19 December 2014
*/


EHcnck - Sat Dec 07 17:21:16 EST 2013

Re: thirdfridayOf
Adamarla - Tue Dec 10 02:59:01 EST 2013

Internationalization may not matter to you, but I work in Germany with a variety of nationalities. To support their setups I would do this (to your code):

const int iMon = 0
const int iTue = 1
const int iWed = 2
const int iThu = 3
const int iFri = 4
const int iSat = 5
const int iSun = 6
 
Date nextDay(Date cDate, int x)
{
    return(dateOnly(dateOf((intOf cDate) + 60*60*24*x)))
} // nextDay
 
Date xDayMonthOf(Date cDate, int iDay, int count) {
    Date oMondayDate = date("05-01-1970", userLocale(), "dd-MM-yyyy")
    string day = stringOf(nextDay(oMondayDate, iDay), userLocale(), "dddd")
 
    const string Month = (stringOf(cDate, userLocale(), "MMMM"))
    const string Year = (stringOf(cDate, userLocale(), "yyyy"))
    int cnt = 1
 
    while((stringOf(cDate, userLocale(), "dddd")) != day) {
        cDate = (string (++cnt " " Month " " Year))
    }
 
    cDate = nextDay(cDate, ((--count)*7))
    if(Month != (stringOf(cDate, userLocale(), "MMMM"))) {
        return (null) Date
    } else {
        return dateOnly(cDate)
    }
} // xDayMonthOf
 
Date xDayMonthOf(int iDay, int count) {
    return xDayMonthOf(today(), iDay, count)
} // xDayMonthOf
 
print xDayMonthOf(today(), iFri, 3) "\n"
print xDayMonthOf(iFri, 3) "\n"
print xDayMonthOf(iMon, 5) "\n"
 
print xDayMonthOf(today(), iFri, 1) "\n"
print xDayMonthOf(iFri, 1) "\n"
 
Date cDate = "20 December 2014"
print xDayMonthOf(cDate, iFri, 3) "\n"

I would also return a null Date on error

- Adam

Re: thirdfridayOf
Mathias Mamsch - Tue Dec 10 07:40:12 EST 2013

Adamarla - Tue Dec 10 02:59:01 EST 2013

Internationalization may not matter to you, but I work in Germany with a variety of nationalities. To support their setups I would do this (to your code):

const int iMon = 0
const int iTue = 1
const int iWed = 2
const int iThu = 3
const int iFri = 4
const int iSat = 5
const int iSun = 6
 
Date nextDay(Date cDate, int x)
{
    return(dateOnly(dateOf((intOf cDate) + 60*60*24*x)))
} // nextDay
 
Date xDayMonthOf(Date cDate, int iDay, int count) {
    Date oMondayDate = date("05-01-1970", userLocale(), "dd-MM-yyyy")
    string day = stringOf(nextDay(oMondayDate, iDay), userLocale(), "dddd")
 
    const string Month = (stringOf(cDate, userLocale(), "MMMM"))
    const string Year = (stringOf(cDate, userLocale(), "yyyy"))
    int cnt = 1
 
    while((stringOf(cDate, userLocale(), "dddd")) != day) {
        cDate = (string (++cnt " " Month " " Year))
    }
 
    cDate = nextDay(cDate, ((--count)*7))
    if(Month != (stringOf(cDate, userLocale(), "MMMM"))) {
        return (null) Date
    } else {
        return dateOnly(cDate)
    }
} // xDayMonthOf
 
Date xDayMonthOf(int iDay, int count) {
    return xDayMonthOf(today(), iDay, count)
} // xDayMonthOf
 
print xDayMonthOf(today(), iFri, 3) "\n"
print xDayMonthOf(iFri, 3) "\n"
print xDayMonthOf(iMon, 5) "\n"
 
print xDayMonthOf(today(), iFri, 1) "\n"
print xDayMonthOf(iFri, 1) "\n"
 
Date cDate = "20 December 2014"
print xDayMonthOf(cDate, iFri, 3) "\n"

I would also return a null Date on error

- Adam

I would think that you can calculate that easily, by knowing one date and the corresponding week day. Knowing for example that the 01.01.1970 was a thursday (I looked that up on my calendar, I came up with the following):

// 01.01.1970 That was a thursday
int weekDay (Date d) { return  (3  + ((intOf d) / 86400)) % 7  }

Date nthWeekday(int n, int day, int month, int year) {
    if (month < 1 || month > 12 || year < 1970 || year > 2102)
       error "Invalid month/year! Must be between 01/1970 and 12/2102";

    string sMonth = (month < 10) ? ("0" month "") : month "";
    int firstDayOfMonth = weekDay date(month "/01/" year "", "MM/dd/yyyy", true);
    int thirdSunday = day - firstDayOfMonth + (n-1)*7;
    return date(month "/" thirdSunday "/" year "", "MM/dd/yyyy", true);
}


print "This Years 1st avent was: " nthWeekday(1, 6, 12, 2013) "\n"
print "This Years 2nd avent was: " nthWeekday(2, 6, 12, 2013) "\n"
print "This Years 3rd avent was: " nthWeekday(3, 6, 12, 2013) "\n"
print "This Years 4th avent was: " nthWeekday(4, 6, 12, 2013) "\n"

I guess the weekday calculation is pretty straightforward. Then once you know what day the first day of the month was, you should be able to calculate the date of the nth weekday easily like shown above.

Regards, Mathias

Re: thirdfridayOf
Adamarla - Wed Dec 11 03:20:42 EST 2013

Mathias Mamsch - Tue Dec 10 07:40:12 EST 2013

I would think that you can calculate that easily, by knowing one date and the corresponding week day. Knowing for example that the 01.01.1970 was a thursday (I looked that up on my calendar, I came up with the following):

// 01.01.1970 That was a thursday
int weekDay (Date d) { return  (3  + ((intOf d) / 86400)) % 7  }

Date nthWeekday(int n, int day, int month, int year) {
    if (month < 1 || month > 12 || year < 1970 || year > 2102)
       error "Invalid month/year! Must be between 01/1970 and 12/2102";

    string sMonth = (month < 10) ? ("0" month "") : month "";
    int firstDayOfMonth = weekDay date(month "/01/" year "", "MM/dd/yyyy", true);
    int thirdSunday = day - firstDayOfMonth + (n-1)*7;
    return date(month "/" thirdSunday "/" year "", "MM/dd/yyyy", true);
}


print "This Years 1st avent was: " nthWeekday(1, 6, 12, 2013) "\n"
print "This Years 2nd avent was: " nthWeekday(2, 6, 12, 2013) "\n"
print "This Years 3rd avent was: " nthWeekday(3, 6, 12, 2013) "\n"
print "This Years 4th avent was: " nthWeekday(4, 6, 12, 2013) "\n"

I guess the weekday calculation is pretty straightforward. Then once you know what day the first day of the month was, you should be able to calculate the date of the nth weekday easily like shown above.

Regards, Mathias

Well, I finished it off:

const int iMon = 0
const int iTue = 1
const int iWed = 2
const int iThu = 3
const int iFri = 4
const int iSat = 5
const int iSun = 6
 
// 01.01.1970 That was a thursday
int weekDay(Date d) { return (3 + ((intOf(d)) / 86400)) % 7 }
 
Date nthWeekday(int iCount, int iWeekDay, int month, int year) {
if (month < 1 || month > 12 || year < 1970 || year > 2102) {
error "Invalid month/year! Must be between 01/1970 and 12/2102";
}
 
int iFirstWeekdayOfMonth = weekDay(date(month "/1/" year "", userLocale(), "M/d/yyyy"));
iWeekDay = (iWeekDay <= iFirstWeekdayOfMonth) ? iWeekDay + 7 : iWeekDay
int iFirstWeekDayDate = iWeekDay - iFirstWeekdayOfMonth
int day = iFirstWeekDayDate + ((iCount - 1) * 7);
 
return date(day "/" month "/"year "", userLocale(), "d/M/yyyy");
}
 
Date nthWeekday(int iCount, int iWeekDay, Date oDate) {
int iMonth = intOf(stringOf(oDate, userLocale(), "M"))
int iYear = intOf(stringOf(oDate, userLocale(), "yyyy"))
return nthWeekday(iCount, iWeekDay, iMonth, iYear)
}
 
print "This Years 1st avent was: " nthWeekday(1, iSun, 12, 2013) "\n"
print "This Years 2nd avent was: " nthWeekday(2, iSun, 12, 2013) "\n"
print "This Years 3rd avent was: " nthWeekday(3, iSun, today()) "\n"
print "This Years 4th avent was: " nthWeekday(4, iSun, today()) "\n"

You may want to add a check that the date is in the same month (& year) as the original - It will be different for large enough n.

-Adam

Re: thirdfridayOf
sekrbo - Wed Dec 11 07:57:45 EST 2013

Adamarla - Wed Dec 11 03:20:42 EST 2013

Well, I finished it off:

const int iMon = 0
const int iTue = 1
const int iWed = 2
const int iThu = 3
const int iFri = 4
const int iSat = 5
const int iSun = 6
 
// 01.01.1970 That was a thursday
int weekDay(Date d) { return (3 + ((intOf(d)) / 86400)) % 7 }
 
Date nthWeekday(int iCount, int iWeekDay, int month, int year) {
if (month < 1 || month > 12 || year < 1970 || year > 2102) {
error "Invalid month/year! Must be between 01/1970 and 12/2102";
}
 
int iFirstWeekdayOfMonth = weekDay(date(month "/1/" year "", userLocale(), "M/d/yyyy"));
iWeekDay = (iWeekDay <= iFirstWeekdayOfMonth) ? iWeekDay + 7 : iWeekDay
int iFirstWeekDayDate = iWeekDay - iFirstWeekdayOfMonth
int day = iFirstWeekDayDate + ((iCount - 1) * 7);
 
return date(day "/" month "/"year "", userLocale(), "d/M/yyyy");
}
 
Date nthWeekday(int iCount, int iWeekDay, Date oDate) {
int iMonth = intOf(stringOf(oDate, userLocale(), "M"))
int iYear = intOf(stringOf(oDate, userLocale(), "yyyy"))
return nthWeekday(iCount, iWeekDay, iMonth, iYear)
}
 
print "This Years 1st avent was: " nthWeekday(1, iSun, 12, 2013) "\n"
print "This Years 2nd avent was: " nthWeekday(2, iSun, 12, 2013) "\n"
print "This Years 3rd avent was: " nthWeekday(3, iSun, today()) "\n"
print "This Years 4th avent was: " nthWeekday(4, iSun, today()) "\n"

You may want to add a check that the date is in the same month (& year) as the original - It will be different for large enough n.

-Adam

Well for me (in Sweden) this works fine for figuring out the 3rd Friday of the month, using the format of the date string.

Locale loc = userLocale

bool thirdFriday (Date d) {
    Date dd = dateOnly (d)
    string sDay = stringOf (dd, loc, "dddd")
    int iDay = intOf (stringOf (dd, loc, "d"))

    if (sDay == "fredag" && (iDay >= 15 && iDay <= 21)) then {
        return true
    } else {
        return false
    }
}

Using a different locale, you naturally have to change the sDay == "fredag" to the appropriate name for a Friday...

/sekrbo

Re: thirdfridayOf
EHcnck - Fri Dec 13 12:10:09 EST 2013

Mathias Mamsch - Tue Dec 10 07:40:12 EST 2013

I would think that you can calculate that easily, by knowing one date and the corresponding week day. Knowing for example that the 01.01.1970 was a thursday (I looked that up on my calendar, I came up with the following):

// 01.01.1970 That was a thursday
int weekDay (Date d) { return  (3  + ((intOf d) / 86400)) % 7  }

Date nthWeekday(int n, int day, int month, int year) {
    if (month < 1 || month > 12 || year < 1970 || year > 2102)
       error "Invalid month/year! Must be between 01/1970 and 12/2102";

    string sMonth = (month < 10) ? ("0" month "") : month "";
    int firstDayOfMonth = weekDay date(month "/01/" year "", "MM/dd/yyyy", true);
    int thirdSunday = day - firstDayOfMonth + (n-1)*7;
    return date(month "/" thirdSunday "/" year "", "MM/dd/yyyy", true);
}


print "This Years 1st avent was: " nthWeekday(1, 6, 12, 2013) "\n"
print "This Years 2nd avent was: " nthWeekday(2, 6, 12, 2013) "\n"
print "This Years 3rd avent was: " nthWeekday(3, 6, 12, 2013) "\n"
print "This Years 4th avent was: " nthWeekday(4, 6, 12, 2013) "\n"

I guess the weekday calculation is pretty straightforward. Then once you know what day the first day of the month was, you should be able to calculate the date of the nth weekday easily like shown above.

Regards, Mathias

wouldn't this work or am I missing something?

const string DayOfTheWeek = "Friday"
Date nthDay(Date cDate, int x)
{
    return(dateOf((intOf cDate) + 60*60*24*x))
} // nextDay

Date xDayMonthOf(Date cDate, string day, int count) {
    const string Month = (stringOf(dateOnly(cDate), userLocale(), "MMMM"))
    const string Year  = (stringOf(dateOnly(cDate), userLocale(), "yyyy"))

    cDate = date(1 "/" Month "/"Year "", userLocale(), "d/MMMM/yyyy")
    while((stringOf(dateOnly(cDate), userLocale(), "dddd")) != DayOfTheWeek) {
        cDate = nthDay(cDate, 1)
    }
    
    cDate = nthDay(cDate, ((count-1)*7))
    if(Month != (stringOf(dateOnly(cDate), userLocale(), "MMMM"))) {
        cDate = null Date
    }
    return cDate
} // xDayMonthOf

Date xDayMonthOf(string day, int count) {
    return xDayMonthOf(today(), day, count)
} // xDayMonthOf

print (dateOnly(today()) == xDayMonthOf(DayOfTheWeek, 3)) "\n"
print (null xDayMonthOf(DayOfTheWeek, 0)) "\n"
print (null xDayMonthOf(DayOfTheWeek, 1)) "\n"
print (null xDayMonthOf(DayOfTheWeek, 2)) "\n"
print (null xDayMonthOf(DayOfTheWeek, 3)) "\n"
print (null xDayMonthOf(DayOfTheWeek, 4)) "\n"
print (null xDayMonthOf(DayOfTheWeek, 5)) "\n"
print (null xDayMonthOf(DayOfTheWeek, 6)) "\n"

/*
Output:
false
true
false
false
false
false
true
true
*/

Re: thirdfridayOf
Mathias Mamsch - Fri Dec 13 14:35:08 EST 2013

EHcnck - Fri Dec 13 12:10:09 EST 2013

wouldn't this work or am I missing something?

const string DayOfTheWeek = "Friday"
Date nthDay(Date cDate, int x)
{
    return(dateOf((intOf cDate) + 60*60*24*x))
} // nextDay

Date xDayMonthOf(Date cDate, string day, int count) {
    const string Month = (stringOf(dateOnly(cDate), userLocale(), "MMMM"))
    const string Year  = (stringOf(dateOnly(cDate), userLocale(), "yyyy"))

    cDate = date(1 "/" Month "/"Year "", userLocale(), "d/MMMM/yyyy")
    while((stringOf(dateOnly(cDate), userLocale(), "dddd")) != DayOfTheWeek) {
        cDate = nthDay(cDate, 1)
    }
    
    cDate = nthDay(cDate, ((count-1)*7))
    if(Month != (stringOf(dateOnly(cDate), userLocale(), "MMMM"))) {
        cDate = null Date
    }
    return cDate
} // xDayMonthOf

Date xDayMonthOf(string day, int count) {
    return xDayMonthOf(today(), day, count)
} // xDayMonthOf

print (dateOnly(today()) == xDayMonthOf(DayOfTheWeek, 3)) "\n"
print (null xDayMonthOf(DayOfTheWeek, 0)) "\n"
print (null xDayMonthOf(DayOfTheWeek, 1)) "\n"
print (null xDayMonthOf(DayOfTheWeek, 2)) "\n"
print (null xDayMonthOf(DayOfTheWeek, 3)) "\n"
print (null xDayMonthOf(DayOfTheWeek, 4)) "\n"
print (null xDayMonthOf(DayOfTheWeek, 5)) "\n"
print (null xDayMonthOf(DayOfTheWeek, 6)) "\n"

/*
Output:
false
true
false
false
false
false
true
true
*/

It probably works. Your original question was if there is a better way to do it... Better can however mean alot, like "shorter" or "smarter" or "faster" or "more readable" or ... My suggestion for example hinted on the fact, that you are doing a lot of unnecessary date conversions and a loop to get to the right date and your code is not as crisp as it could be. Adam hinted on removing the hardcoded "Friday" so people with a different userLocale() (e.g. german) would still be able to run your code. All variants work of course. It is totally up to you, if you want to use the suggestions. Regards, Mathias